package com.dl.study.module.user.strategy.proccesor;

import com.dl.study.module.user.strategy.anno.OrderTypeHandlerAnno;
import com.dl.study.module.user.strategy.context.HandlerContext;
import com.dl.study.module.user.strategy.handler.AOrderTypeHandler;
import com.dl.study.module.user.strategy.userenum.UserTypeEnum;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;


/**
 * @Author: user
 * @Date: 2021/11/4 14:42
 * @Description: 策略模式，处理type与实现类的映射关系
 */

@Component
public class HandlerProccessor implements BeanFactoryPostProcessor {


    /**
     * 扫描@OrderTypeHandlerAnno注解，初始化HandlerContext，将其注册到spring容器
     *
     * @param beanFactory bean工厂
     * @throws BeansException
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        Map<String, AOrderTypeHandler> handlerMap = new HashMap<>();
        for (UserTypeEnum temp : UserTypeEnum.values()) {
            AOrderTypeHandler beanInstacle = getBeansWithAnnotation(beanFactory, AOrderTypeHandler.class, OrderTypeHandlerAnno.class, temp.getCode());
            handlerMap.put(temp.getCode(), beanInstacle);
        }
        HandlerContext context = new HandlerContext(handlerMap);
        //单例注入
        beanFactory.registerSingleton(HandlerContext.class.getName(), context);
    }


    /*
     * 通过父类+注解找到实体类
     */
    private <T> T getBeansWithAnnotation(ConfigurableListableBeanFactory beanFactory, Class<T> manager, Class<? extends OrderTypeHandlerAnno> annotation, String code) throws BeansException {
        if (ObjectUtils.isEmpty(code)) {
            throw new RuntimeException("code is null ");
        }
        Collection<T> tCollection = beanFactory.getBeansOfType(manager).values();
        for (T t : tCollection) {
            OrderTypeHandlerAnno orderTypeHandlerAnno = t.getClass().getAnnotation(annotation);
            if (ObjectUtils.isEmpty(orderTypeHandlerAnno)) {
                throw new RuntimeException("该注解没有写入值 :" + code);
            }
            //注解值是否与code相等
            if (code.equals(orderTypeHandlerAnno.value().getCode())) {
                return t;
            }
        }
        throw new RuntimeException("通过code没有找到该注解对应的实体类 :" + code);
    }

}
